{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Resource Estimation for Double-factorized Chemistry\n",
    "\n",
    "In this notebook we evaluate the physical resource estimates of using the\n",
    "so-called _double-factorized qubitization_ algorithm described in [[Phys. Rev.\n",
    "Research 3, 033055 (2021)](https://doi.org/10.1103/PhysRevResearch.3.033055)] to\n",
    "calculate the energy of a user provided Hamiltonian to chemical accuracy of 1\n",
    "mHa.  The Hamiltonian is provided in terms of an FCIDUMP file that is accessible\n",
    "via an HTTPS URI.\n",
    "\n",
    "The _qubitization_ approach is based on quantum phase estimation, but instead of\n",
    "constructing the standard $U = \\exp{(-i H/\\alpha)}$ from the Hamiltonian matrix\n",
    "$H$, one takes $U = \\exp{(-i \\sin^{-1} (H/\\alpha))}$, which can typically be\n",
    "implemented with fewer resources. Using _double-factorization_, $H$ is\n",
    "represented compactly through a combination of a judicious choice of orbitals\n",
    "and compression. The tolerated total error budget is $\\epsilon = 0.01$,\n",
    "corresponding to $1\\%$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Getting started\n",
    "\n",
    "We import several Python classes and functions from `azure.quantum`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from azure.quantum import Workspace\n",
    "from azure.quantum.target.microsoft import MicrosoftEstimator\n",
    "from azure.quantum.chemistry import df_chemistry"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We connect to the Azure Quantum workspace by creating a new workspace."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "workspace = Workspace(\n",
    "    resource_id=\"\",\n",
    "    location=\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This workspace is then used to create an instance to the Resource Estimator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "estimator = MicrosoftEstimator(workspace)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Configuring a resource estimation job\n",
    "\n",
    "We start by creating a parameter instance for the resource estimator, which allows us to configure all parameters associated to the estimation job.  In this scenario, we want to evaluate estimates for six different qubit parameter configurations, therefore we set the number of items in the job to 6."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "params = estimator.make_params(num_items=6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we are providing a link to the FCIDUMP file that describes the Hamiltonian, which is passed via a URI. For example, you can choose some of the following URIs:\n",
    "\n",
    "| URI                                          | Instance name         | Description                                                                                                                                                                                               |\n",
    "|----------------------------------------------|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n",
    "| https://aka.ms/fcidump/XVIII-cas4-fb-64e-56o | XVIII-cas4-fb-64e-56o | 64 electron, 56 orbital active space of one of the stable intermediates in the [ruthenium-catalyzed carbon fixation cycle](https://journals.aps.org/prresearch/abstract/10.1103/PhysRevResearch.3.033055) |\n",
    "| https://aka.ms/fcidump/nitrogenase-54e-54o   | nitrogenase-54e-54o   | 54 electron, 54 orbital active space of the active core of the nitrogenase that is used in [this paper](https://www.pnas.org/doi/10.1073/pnas.1619152114)                                                 |\n",
    "| https://aka.ms/fcidump/fe2s2-10e-40o         | fe2s2-10e-40o         | 10 electron, 40 orbital active space of [2Fe, 2S] cluster that is shown in [this paper](https://www.nature.com/articles/nchem.2041)                                                                       |\n",
    "| https://aka.ms/fcidump/polyyne-24e-24o       | polyyne-24e-24o       | 24 electron, 24 orbital active space of the polyyne molecule                                                                                                                                              |\n",
    "| https://aka.ms/fcidump/n2-10e-8o             | n2-10e-8o             | 10 electron, 8 orbital active space of he dissociated nitrogen at 3 Angstrom distance                                                                                                                     |\n",
    "\n",
    "You can also pass your own FCIDUMP files via \n",
    "* [raw links to files in Github](https://docs.github.com/repositories/working-with-files/using-files/viewing-a-file#viewing-or-copying-the-raw-file-content) repositories (see how to [add files to Github repositories](https://docs.github.com/repositories/working-with-files/managing-files/creating-new-files))\n",
    "* [files on Github gists](https://docs.github.com/get-started/writing-on-github/editing-and-sharing-content-with-gists/creating-gists)\n",
    "* [files in Azure Blob Storage](https://learn.microsoft.com/azure/storage/blobs/storage-blobs-introduction) using [SAS tokens](https://learn.microsoft.com/azure/cognitive-services/translator/document-translation/how-to-guides/create-sas-tokens?tabs=Containers#create-sas-tokens-in-the-azure-portal)\n",
    "\n",
    "The URI is passed to the parameters as so called file URI with the name `\"fcidumpUri\"`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "params.file_uris[\"fcidumpUri\"] = \"https://aka.ms/fcidump/XVIII-cas4-fb-64e-56o\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The quantum algorithms requires a total accuracy if 0.01, i.e., 1%, in order to obtain a chemical accuracy of 1 mHa.  We can instruct the resource estimator to use a total error budget of 0.01, which is distributed to all possible sub components in the execution of the quantum algorithm that may fail. (More details on the error budget can be found in the [Azure Quantum documentation](https://learn.microsoft.com/azure/quantum/overview-resources-estimator#error-budget).)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "params.error_budget = 0.01"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, we are specifying the qubit parameters.  Here we are choosing all six pre-defined qubit parameter models.  These are four gate-based models with operation times in the microsecond and nanosecond regime, as well as assumptions on their physical error rates of $10^{-3}$ and $10^{-4}$, respectively.  The other two are Majorana based models with operation times in the nanosecond regime and physical error rates of $10^{-4}$ and $10^{-6}$.  For the Majorana based models we assume a Floquet code as QEC scheme.  More details on these parameters and assumptions, as well as how to customize these, can be found in the [Azure Quantum documentation](https://learn.microsoft.com/azure/quantum/overview-resources-estimator)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "params.items[0].qubit_params.name = \"qubit_gate_us_e3\"\n",
    "params.items[1].qubit_params.name = \"qubit_gate_us_e4\"\n",
    "params.items[2].qubit_params.name = \"qubit_gate_ns_e3\"\n",
    "params.items[3].qubit_params.name = \"qubit_gate_ns_e4\"\n",
    "params.items[4].qubit_params.name = \"qubit_maj_ns_e4\"\n",
    "params.items[4].qec_scheme.name = \"floquet_code\"\n",
    "params.items[5].qubit_params.name = \"qubit_maj_ns_e6\"\n",
    "params.items[5].qec_scheme.name = \"floquet_code\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The parameters are now all set up, and we are ready to go to submit the resource estimation job. As quantum program, we are using the double-factorization based quantum chemistry algorithm, which is provided via the `df_chemistry` function.  The execution of this cell may take a few minutes depending on program size.  Once the job is finished, we are obtaining the results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "job = estimator.submit(df_chemistry(), input_params=params)\n",
    "results = job.get_results()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Analyzing the results\n",
    "\n",
    "Finally, we are presenting the experimental results using a summary table."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "labels = [\"Gate-based µs, 10⁻³\", \"Gate-based µs, 10⁻⁴\", \"Gate-based ns, 10⁻³\", \"Gate-based ns, 10⁻⁴\", \"Majorana ns, 10⁻⁴\", \"Majorana ns, 10⁻⁶\"]\n",
    "\n",
    "results.summary_data_frame(labels=labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each row corresponds to one of the six qubit parameter configurations, where the first column shows a textual description for the model.  The next three columns show technology-independent resources, which are the number of logical qubits, the logical depth, which is the number of logical operations performed in sequence, as well as the number of T states that are consumed by the logical operations.  T states originate from complex operations in the quantum algorithm, e.g., Toffoli gates or rotation gates.\n",
    "\n",
    "Next, the code distance indicates the error correction overhead to guarantee a sufficient logical error rate for the logical operations.  The number of T factories indicates how many T factories are executed in parallel to produce the total number of T states.  The T factory fraction describes the percentage of the number of qubits that are used to execute T factories, the rest is used to execute the logical operations of the algorithm.  Finally, the last two columns show the total number of physical qubits and the wall clock runtime to execute the quantum algorithm given the assumed qubit parameters."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Detailed resource estimates\n",
    "\n",
    "We can also have a more detailed look into the resource estimates.  Here we show the details for the last configuration (index 5).  The output is a table with the overall physical resource counts. You can further inspect more details about the resource estimates by collapsing various groups which have more information. For example, if you collapse the Logical qubit parameters group, you can see how the overhead to represent a logical qubit using physical qubits is derived. The last group shows the physical qubit properties that were assumed for this estimation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "results[5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also compare different configurations.  In this case we compare the gate-based nanosecond model with the Majorana based model for an error rate of $10^{-4}$.  These correspond to indices 3 and 4, not that intervals in Python are half-open."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "results[3:5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Next steps"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook, you've estimated the quantum computing requirements to calculate the energy of a Hamiltonian. Nice job! 👏🏽\n",
    "\n",
    "The numbers for the XVIII-cas4-fb-64e-56o instance roughly match the numbers in\n",
    "the paper [Assessing requirements for scaling quantum computers to real-world\n",
    "impact](https://aka.ms/AQ/RE/Paper), as we incorporated a few improvements in\n",
    "the implementation of the double-factorized chemistry algorithm as compared to\n",
    "the version used when the paper was published.\n",
    "\n",
    "We hope that this notebook was helpful to you.  Here are some suggestions for next steps:\n",
    "* Try to estimate some custom FCIDUMP files\n",
    "* Investigate the details of resource estimation by exploring the detailed resource estimation tables\n",
    "* Modify the assumptions on the target quantum computer by providing custom qubit parameters\n",
    "* Check out the other resource estimation sample notebooks in the Azure Quantum sample gallery"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ℹ️ Relationship with VQE sample\n",
    "\n",
    "You may already be familiar with our [Variational Quantum Eigensolver (VQE) sample notebook](https://github.com/microsoft/Quantum/blob/main/samples/azure-quantum/variational-quantum-eigensolver/VQE-qiskit-hydrogen-session.ipynb), which also takes as input Hamiltonians recorded in FCIDUMP format. VQE algorithms are useful for building an understanding of the current limits of quantum hardware for the purposes of education and research. In the longer term, we will simulate quantum systems using more efficient algorithms tailored for large-scale fault-tolerant quantum hardware.\n",
    "\n",
    "Notable simulation algorithms, such as qubitization, quantum signal processing, or trotterization, can be used as subroutines in the quantum phase estimation (QPE) algorithm to obtain high-accuracy energy estimates of a targeted eigenstate. The Azure Quantum Resource Estimator is designed with these long-term algorithms (particularly QPE + qubitization) in mind (rather than VQE).\n",
    "\n",
    "Please be aware that while you may use the FCIDUMP files included in the [VQE sample](https://github.com/microsoft/Quantum/blob/main/samples/azure-quantum/variational-quantum-eigensolver/VQE-qiskit-hydrogen-session.ipynb) to generate resource estimates in this end-to-end chemistry sample, the VQE samples provided are for very small systems that we can simulate using VQE optimized for quantum hardware today. As the current QPE + qubitization implementation is optimized for large-scale fault-tolerant quantum hardware, the quantum resource estimates generated by the Resource Estimator will be much larger than what is required to run VQE for these systems.\n",
    "\n",
    "The FCIDUMP sample files provided in this chemistry end-to-end sample are too large to run using VQE on today's quantum systems, so they will not work in the VQE notebook."
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
